home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 August: Tool Chest / Dev.CD Aug 94.toast / New System Software Extensions / OpenDoc A6 / OpenDoc Parts Framework / OPF / Found / FWExcLib / Sources / FWNewHel.cpp < prev    next >
Encoding:
Text File  |  1994-04-21  |  11.6 KB  |  363 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                FWNewHel.cpp
  4. //    Release Version:    $ 1.0d1 $
  5. //
  6. //    Creation Date:        3/28/94
  7. //
  8. //    Copyright:    © 1994 by Apple Computer, Inc., all rights reserved.
  9. //
  10. //========================================================================================
  11.  
  12. #ifndef FWNEWHEL_H
  13. #include "FWNewHel.h"
  14. #endif
  15.  
  16. #ifndef FWEXCDEF_H
  17. #include "FWExcDef.h"
  18. #endif
  19.  
  20. #ifndef   FWPRIMEM_H
  21. #include "FWPriMem.h"
  22. #endif
  23.  
  24. #ifdef FW_BUILD_MAC
  25. #pragma segment BEL
  26. #endif
  27.  
  28. //========================================================================================
  29. //    CLASS _FW_CPrivSubHelper
  30. //========================================================================================
  31.  
  32. void _FW_CPrivSubHelper::InitializeStorageArray(FW_SPrivExceptionGlobals& globals,
  33.                                                 _FW_CPrivSubHelper*array, int size)
  34. {
  35.     for (int i=0; i<size-1; i++)
  36.     {
  37.         array[i].fSiblings = array+i+1;
  38. #ifdef FW_DEBUG
  39.         array[i].fSubObject = 0;
  40.         array[i].fSubObjectSize = 0;
  41.         array[i].fSubObjectVTable = 0;
  42. #endif
  43.     }
  44.     array[size-1].fSiblings = NULL;
  45.     globals.gSubHelperFreeListHead = array;
  46. }
  47.  
  48. //----------------------------------------------------------------------------------------
  49. //    _FW_CPrivSubHelper::operator new
  50. //----------------------------------------------------------------------------------------
  51.  
  52. void* _FW_CPrivSubHelper::operator new(size_t size)
  53. {
  54.     FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
  55.     _FW_CPrivSubHelper* head = globals.gSubHelperFreeListHead;
  56.     FW_PRIV_ASSERT(head != NULL);
  57.     globals.gSubHelperFreeListHead = head->fSiblings;
  58.     return (void*) head;
  59. }
  60.  
  61. //----------------------------------------------------------------------------------------
  62. //    _FW_CPrivSubHelper::operator delete
  63. //----------------------------------------------------------------------------------------
  64.  
  65. void  _FW_CPrivSubHelper::operator delete(void* object)
  66. {
  67.     FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
  68.     _FW_CPrivSubHelper* subHelper = (_FW_CPrivSubHelper*) object;
  69.     _FW_CPrivSubHelper* head = globals.gSubHelperFreeListHead;
  70.     subHelper->fSiblings = head;
  71. #ifdef FW_DEBUG
  72.     subHelper->fSubObject = 0;
  73.     subHelper->fSubObjectSize = 0;
  74.     subHelper->fSubObjectVTable = 0;
  75. #endif
  76.     globals.gSubHelperFreeListHead = subHelper;
  77. }
  78.  
  79. //----------------------------------------------------------------------------------------
  80. //    _FW_CPrivSubHelper::_FW_CPrivSubHelper
  81. //----------------------------------------------------------------------------------------
  82.  
  83. _FW_CPrivSubHelper::_FW_CPrivSubHelper(_FW_CAutoDestructObject *subObject, 
  84.                                        size_t subObjectSize,
  85.                                        _FW_CPrivSubHelper *nextSubHelper)
  86. {
  87.     fSubObject = subObject;
  88.     fSubObjectSize = subObjectSize;
  89.     fSubObjectVTable = *(void**)subObject;
  90.     fSiblings = nextSubHelper;
  91. }
  92.  
  93. //----------------------------------------------------------------------------------------
  94. //    _FW_CPrivSubHelper::~_FW_CPrivSubHelper
  95. //----------------------------------------------------------------------------------------
  96.  
  97. _FW_CPrivSubHelper::~_FW_CPrivSubHelper()
  98. {
  99. }
  100.  
  101. //========================================================================================
  102. //    CLASS _FW_CPrivNewHelper
  103. //========================================================================================
  104.  
  105. //----------------------------------------------------------------------------------------
  106. //    _FW_CPrivNewHelper::Initialize
  107. //----------------------------------------------------------------------------------------
  108.  
  109. void _FW_CPrivNewHelper::Initialize(FW_SPrivExceptionGlobals& globals)
  110. {
  111.     globals.gNewHelperStackBottom = (_FW_CPrivNewHelper **) 
  112.                             ::FW_PrimitiveAllocateBlock(kNewHelperStackSize);
  113.  
  114.     globals.gNewHelperStackTop = globals.gNewHelperStackBottom;
  115.     
  116.     globals.gSubHelperStorageArray = (_FW_CPrivSubHelper *) 
  117.                             ::FW_PrimitiveAllocateBlock(kSubHelperArrayByteSize);
  118.  
  119.     _FW_CPrivSubHelper::InitializeStorageArray(globals,
  120.                             globals.gSubHelperStorageArray,
  121.                             kSubHelperArraySize);
  122. }
  123.     
  124. //----------------------------------------------------------------------------------------
  125. //    _FW_CPrivNewHelper::Terminate
  126. //----------------------------------------------------------------------------------------
  127.  
  128. void _FW_CPrivNewHelper::Terminate()
  129. {
  130.     FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
  131.     ::FW_PrimitiveFreeBlock(globals.gSubHelperStorageArray);
  132.     ::FW_PrimitiveFreeBlock(globals.gNewHelperStackBottom);
  133. }
  134.  
  135. //----------------------------------------------------------------------------------------
  136. //    _FW_CPrivNewHelper::_FW_CPrivNewHelper
  137. //----------------------------------------------------------------------------------------
  138.  
  139. _FW_CPrivNewHelper::_FW_CPrivNewHelper(__FW_OperatorNewHandler newHandler,
  140.                                       __FW_OperatorDeleteHandler deleteHandler) :
  141.     fWatchedObject(0),
  142.     fObjectVTable(0),
  143.     fWatchedSize(0),
  144.     fSubHelperList(0),
  145.     fNewHandler(newHandler),
  146.     fDeleteHandler(deleteHandler)
  147. {
  148.     PushNewHelper();
  149.     FW_END_CONSTRUCTOR
  150. }
  151.  
  152. //----------------------------------------------------------------------------------------
  153. //    _FW_CPrivNewHelper::~_FW_CPrivNewHelper
  154. //----------------------------------------------------------------------------------------
  155.  
  156. _FW_CPrivNewHelper::~_FW_CPrivNewHelper()
  157. {
  158.     FW_START_DESTRUCTOR
  159.     if (fWatchedObject != 0)
  160.     {
  161.         DeleteWatchedObject();
  162.         _FW_CPrivNewHelper *temp = _FW_CPrivNewHelper::PopNewHelper();
  163.         FW_PRIV_ASSERT(temp == this);
  164.     }
  165.     else
  166.     {
  167.         FW_PRIV_ASSERT(fSubHelperList == 0);
  168.     }
  169. }
  170.  
  171. //----------------------------------------------------------------------------------------
  172. //    _FW_CPrivNewHelper::DeleteWatchedObject
  173. //----------------------------------------------------------------------------------------
  174.  
  175. void _FW_CPrivNewHelper::DeleteWatchedObject()
  176. {
  177.     _FW_CPrivSubHelper    *next = fSubHelperList;
  178.     while (next != NULL)
  179.     {
  180.         _FW_CAutoDestructObject *subObject = next->fSubObject;
  181.         *(void**)subObject = next->fSubObjectVTable;
  182.         subObject->__Delete();
  183.  
  184.         // Save next->fSiblings before deleting next! (see operator delete)
  185.         _FW_CPrivSubHelper    *temp = next;
  186.         next = next->fSiblings;
  187.         delete temp;
  188.     }
  189.     if (fObjectVTable != 0)
  190.     {
  191.         *(void**)fWatchedObject = fObjectVTable;
  192.         fWatchedObject->__Delete();
  193.     }
  194.     _FW_CAutoDestructObject::operator delete((void*) fWatchedObject);
  195. }
  196.  
  197. //----------------------------------------------------------------------------------------
  198. //    _FW_CPrivNewHelper::WatchObject
  199. //
  200. //        This method is not really const, 
  201. //        but it reduces unnecessary warnings to declare it so.
  202. //----------------------------------------------------------------------------------------
  203.  
  204. _FW_CAutoDestructObject * _FW_CPrivNewHelper::WatchObject(
  205.                                 _FW_CAutoDestructObject *watchedObject,
  206.                                 size_t watchedSize) const
  207. {
  208.     _FW_CPrivNewHelper *self = (_FW_CPrivNewHelper *) this;
  209.     _FW_CAutoDestructObject *previous = fWatchedObject;
  210.     self->fWatchedObject = watchedObject;
  211.     self->fWatchedSize = watchedSize;
  212.     return previous;
  213. }
  214.  
  215. //----------------------------------------------------------------------------------------
  216. //    _FW_CPrivNewHelper::ForgetObject
  217. //
  218. //        This method is not really const, 
  219. //        but it reduces unnecessary warnings to declare it so.
  220. //----------------------------------------------------------------------------------------
  221.  
  222. _FW_CAutoDestructObject * _FW_CPrivNewHelper::ForgetObject() const
  223. {
  224.     _FW_CPrivNewHelper *self = (_FW_CPrivNewHelper *) this;
  225.     _FW_CAutoDestructObject *previous = fWatchedObject;
  226.     self->fWatchedObject = 0;
  227.     FW_PRIV_ASSERT(fSubHelperList == 0);
  228.     return previous;
  229. }
  230.  
  231. //----------------------------------------------------------------------------------------
  232. //    _FW_CPrivNewHelper::PopNewHelper
  233. //----------------------------------------------------------------------------------------
  234.  
  235. _FW_CPrivNewHelper* _FW_CPrivNewHelper::PopNewHelper()
  236. {
  237.     FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
  238.     _FW_CPrivNewHelper** top = globals.gNewHelperStackTop;
  239. #ifdef FW_DEBUG
  240.     _FW_CPrivNewHelper** bottom = globals.gNewHelperStackBottom;
  241.     FW_PRIV_ASSERT(top > bottom);
  242. #endif
  243.     _FW_CPrivNewHelper*    helper = *--top;
  244.     globals.gNewHelperStackTop = top;
  245.     return helper;
  246. }
  247.  
  248. //----------------------------------------------------------------------------------------
  249. //    _FW_CPrivNewHelper::TopNewHelper
  250. //----------------------------------------------------------------------------------------
  251.  
  252. _FW_CPrivNewHelper* _FW_CPrivNewHelper::TopNewHelper()
  253. {
  254.     FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
  255.     _FW_CPrivNewHelper** top = globals.gNewHelperStackTop;
  256.     _FW_CPrivNewHelper** bottom = globals.gNewHelperStackBottom;
  257.     _FW_CPrivNewHelper*    helper = 0;
  258.     if (top > bottom)
  259.         helper = top[-1];
  260.     return helper;
  261. }
  262.  
  263. //----------------------------------------------------------------------------------------
  264. //    _FW_CPrivNewHelper::PushNewHelper
  265. //----------------------------------------------------------------------------------------
  266.  
  267. void _FW_CPrivNewHelper::PushNewHelper()
  268. {
  269.     FW_SPrivExceptionGlobals& globals = FW_CExceptionTaskGlobals::GetExceptionGlobals();
  270.     _FW_CPrivNewHelper** top = globals.gNewHelperStackTop;
  271. #ifdef FW_DEBUG
  272.     _FW_CPrivNewHelper** bottom = globals.gNewHelperStackBottom;
  273.     FW_PRIV_ASSERT(top < bottom + kMaxNewHelperStackItems);
  274. #endif
  275.     *top++ = this;
  276.     globals.gNewHelperStackTop = top;
  277. }
  278.  
  279. //----------------------------------------------------------------------------------------
  280. //    _FW_CPrivSubHelper::InList
  281. //----------------------------------------------------------------------------------------
  282.  
  283. _FW_CPrivSubHelper* _FW_CPrivNewHelper::InList(_FW_CAutoDestructObject *subObject)
  284. {
  285.     _FW_CPrivSubHelper *next = fSubHelperList;
  286.     while (next != NULL)
  287.     {
  288.         if (next->fSubObject == subObject)
  289.             break;
  290.         next = next->fSiblings;
  291.     }
  292.     return next;
  293. }
  294.  
  295. //----------------------------------------------------------------------------------------
  296. //    _FW_CPrivNewHelper::UpdateForEndConstructor
  297. //----------------------------------------------------------------------------------------
  298.  
  299. void _FW_CPrivNewHelper::UpdateForEndConstructor(_FW_CAutoDestructObject *object, size_t size)
  300. {
  301.     if (object == fWatchedObject)
  302.     {
  303.         // Object is the object that was FW_NEWed.
  304.         // Update the helper's copy of the vtbl pointer.
  305.         fObjectVTable = *(void**)fWatchedObject;
  306.         FW_PRIV_ASSERT(fObjectVTable != 0);
  307.     }
  308.     else
  309.     {
  310.         // Object must be a subobject of the object that was FW_NEWed.
  311.         FW_PRIV_ASSERT(IsSubObject(object, fWatchedObject, fWatchedSize));
  312.         
  313.         // Is this subobject already attached, partially constructed?
  314.         _FW_CPrivSubHelper* subHelper = InList(object);
  315.         if (subHelper==NULL)
  316.         {
  317.             // No, create a new helper to track this subobject
  318.             fSubHelperList = new _FW_CPrivSubHelper(object, size, fSubHelperList);
  319.         }
  320.         else
  321.         {
  322.             // Yes, update its vtable
  323.             subHelper->fSubObjectVTable = *(void**)object;
  324.             FW_PRIV_ASSERT(subHelper->fSubObjectVTable != 0);
  325.         }
  326.     }
  327.         
  328.     // Now, release any nested subobjects of this object
  329.     // First, remove from head of list, updating fSubHelperList
  330.     while (fSubHelperList != NULL && IsSubObject(fSubHelperList->fSubObject, object, size))
  331.     {
  332.         // Save fSubHelperList->fSiblings before deleting fSubHelperList!
  333.         _FW_CPrivSubHelper *temp = fSubHelperList;
  334.         fSubHelperList = fSubHelperList->fSiblings;
  335.         delete temp;
  336.     }
  337.     
  338.     // Second, remove from internal to list, with fSubHelperList frozen
  339.     if (fSubHelperList != NULL)
  340.     {
  341.         FW_PRIV_ASSERT(!IsSubObject(fSubHelperList->fSubObject, object, size));
  342.         _FW_CPrivSubHelper* prev = fSubHelperList;
  343.         _FW_CPrivSubHelper* next = prev->fSiblings;
  344.         while (next!=NULL)
  345.         {
  346.             if (IsSubObject(next->fSubObject, object, size))
  347.             {
  348.                 // unlink & delete next.
  349.                 prev->fSiblings = next->fSiblings;
  350.                 delete next;
  351.                 next = prev->fSiblings;
  352.             }
  353.             else
  354.             {
  355.                 // advance prev to next
  356.                 prev = next;
  357.                 next = prev->fSiblings;
  358.             }
  359.         }
  360.     }
  361. }
  362.  
  363.